package core;

public abstract class Actor extends Element {
	/* Maximum HP */
	private static final int MAX_HP = 99;
	/* Starting HP */
	private static final int START_HP = 9;
	/* Current health points */
	private int hp;
	/* Current maximum health points */
	private int maxHp;
	/* Weapon */
	private Weapon weapon;

	public Actor() {
		super();
		weapon = new Weapon();
		hp = maxHp = START_HP;
	}

	public Actor(int pos) {
		super();
		weapon = new Weapon();
		this.hp = this.maxHp = START_HP;
		this.setPos(pos);
	}

	public Actor(int pos, int hp, int maxHp) {
		super();
		weapon = new Weapon();
		this.hp = hp;
		this.maxHp = maxHp;
		this.setPos(pos);
	}

	public int getHp() {
		return hp;
	}

	public void setHp(int hp) {
		if (hp < MAX_HP)
			this.hp = hp;
	}

	public int getMaxHp() {
		return maxHp;
	}

	public Weapon getWeapon() {
		return weapon;
	}

	public void levelUp() {
		intLevelUp();
	}

	public boolean fight(Actor enemy) {
		return intFight(enemy);
	}

	public boolean move(char c, Room room) {
		return intMove(c, room);
	}

	public abstract boolean usePotion(Potion p, Room room);

	private void intLevelUp() {
		if (hp + 2 <= maxHp)
			hp += 2;
		else
			hp = maxHp;
		// weapon.levelUp();
	}

	private boolean intFight(Actor enemy) {
		if (this.getPos() == enemy.getPos()) {
			while ((this.getHp() > 0) && (enemy.getHp() > 0)) {
				int damage = weapon.hit();
				if (damage == 0)
					return false;
				else {
					if ((enemy.getHp() - damage) <= 0) {
						enemy.setHp(0);
					} else
						enemy.setHp(enemy.getHp() - damage);
					return true;
				}
			}
		}
		return false;
	}

	/* Movements */
	private boolean intMove(char c, Room room) {
		int movePos;
		switch (c) {
		case 'u':
			movePos = this.getPos() - (room.getLongSide() + 1);
			break;
		case 'i':
			movePos = this.getPos() - room.getLongSide();
			break;
		case 'o':
			movePos = this.getPos() - (room.getLongSide() - 1);
			break;
		case 'j':
			movePos = this.getPos() - 1;
			break;
		case 'k':
			movePos = this.getPos();
			break;
		case 'l':
			movePos = this.getPos() + 1;
			break;
		case 'm':
			movePos = this.getPos() + (room.getLongSide() - 1);
			break;
		case ',':
			movePos = this.getPos() + room.getLongSide();
			break;
		case '.':
			movePos = this.getPos() + (room.getLongSide() + 1);
			break;
		default:
			movePos = this.getPos();
		}
		/* Out of the room limits */
		if ((movePos < 0)
				|| (movePos >= (room.getLongSide() * room.getShortSide())))
			return false;
		/* If it is moving into a wall */
		for (Wall w : room.getLimits())
			if (w.getPos() == movePos)
				return false;
		/* Remove the element from the current position */
		room.removeElement(this);
		this.setPos(movePos);
		/* Need to check if it has to fight with something, or pick up a potion */
		/* If there's another actor, fight with it */
		if (room.getElement(movePos / room.getLongSide(),
				movePos % room.getLongSide()) instanceof Actor) {
			Actor a = (Actor) room.getElement(movePos / room.getLongSide(),
					movePos % room.getLongSide());
			while ((this.getHp() > 0) && (a.getHp() > 0)) {
				this.fight(a);
				if (a.getHp() > 0)
					a.fight(this);
				else
					room.removeElement(a);
			}
		}
		/* If there's a potion, pick it up */
		else if (room.getElement(movePos / room.getLongSide(),
				movePos % room.getLongSide()) instanceof Potion) {
			Potion p = (Potion) room.getElement(movePos / room.getLongSide(),
					movePos % room.getLongSide());
			this.usePotion(p, room);
		}
		if (this.getHp() > 0)
			room.addElement(this);
		return true;
	}

	@Override
	public String toString() {
		return "Actor [hp=\"" + hp + "\", maxHp=\"" + maxHp + "\"]"
				+ super.toString();
	}

}
